package com.shenhaofeng.permissions;

import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * <p>权限请求器,在23之后的版本targetSdkVersion>=23权限即使在清单中获取，用户仍旧能够关闭或拒绝该权限，因此现在需要一个权限管理器来统一高低版本的权限请求<p/>
 * <p>在低版本的设备上，请求权限如果在清单中已注明将会直接返回权限结果<p/>
 * Created by haofeng on 2016/9/24.
 */

public class PermissionsRequester {

    private Context mContext;
    private int mRequestCode;
    private PermissionsSource mSource;
    private PermissionsListener mListener;
    private CharSequence mRationale;
    private Component mComponent;
    private Activity mActivity;
    private Fragment mFragment;

    public PermissionsRequester(int mRequestCode, PermissionsSource mSource, PermissionsListener mListener, CharSequence mRationale, Component mComponent, Activity mActivity, Fragment mFragment) {
        this.mRequestCode = mRequestCode;
        this.mSource = mSource;
        this.mListener = mListener;
        this.mRationale = mRationale;
        this.mComponent = mComponent;
        this.mActivity = mActivity;
        this.mFragment = mFragment;
    }

    /**
     * 请求权限
     *
     * @param permissions 需要请求的权限
     */
    public void requestPermissions(@NonNull String firstPermission, String... permissions) {
        String[] firstPermissions = new String[]{firstPermission};
        String[] allPermissions = Arrays.copyOf(firstPermissions, firstPermissions.length + permissions.length);
        System.arraycopy(permissions, 0, allPermissions, firstPermissions.length, permissions.length);
        //首先检查是否以获取权限
        List<String> granted = new ArrayList<>();//已获取的权限
        List<String> denied = new ArrayList<>();//未获取的权限
        for (int i = 0; i < allPermissions.length; i++) {
            String permission = allPermissions[i];
            if (checkSelfPermissions(getContext(), permission)) {
                granted.add(permission);
            } else {
                denied.add(permission);
            }
        }
        if (denied.isEmpty()) {
            //没有被禁止的权限,直接处理结果
            mListener.onPermissionResult(mRequestCode, granted, denied);
            return;
        }
        //绑定结果数据源
        mSource.onBindRequestPermissionsResultSource(new PermissionsResultSourceImpl());
        boolean shouldShowRequestPermissionRationale = false;
        //请求尚未获取的权限
        if(!TextUtils.isEmpty(mRationale)){
            //在提示信息部位空的情况下可能弹出理由说明的弹窗
            for (String permission : denied) {
                //检查是否需要提示用户权限的请求理由
                if (shouldShowRequestPermissionRationale(permission)) {
                    shouldShowRequestPermissionRationale = true;
                    showRationale(Arrays.asList(allPermissions));
                    break;
                }
            }
        }
        //如果不需要说明理由，直接请求
        if (!shouldShowRequestPermissionRationale) {
            componentRequestPermissions(Arrays.asList(allPermissions));
        }
    }

    /**
     * 通知组件请求权限
     *
     * @param permissionList
     */
    private void componentRequestPermissions(List<String> permissionList) {
        String[] permissions = String[].class.cast(permissionList.toArray());
        switch (mComponent) {
            case ACTIVITY: {
                ActivityCompat.requestPermissions(mActivity, permissions, mRequestCode);
                break;
            }
            case FRAGMENT: {
                mFragment.requestPermissions(permissions, mRequestCode);
                break;
            }
        }
    }


    /**
     * 检查是否需要弹出申请权限的理由
     *
     * @param permission
     * @return
     */
    private boolean shouldShowRequestPermissionRationale(String permission) {
        switch (mComponent) {
            case ACTIVITY: {
                return ActivityCompat.shouldShowRequestPermissionRationale(mActivity, permission);
            }
            case FRAGMENT: {
                return mFragment.shouldShowRequestPermissionRationale(permission);
            }
        }
        return false;
    }

    /**
     * 显示请求权限的理由
     *
     * @param permissions
     */
    private void showRationale(final List<String> permissions) {
        new AlertDialog.Builder(getContext())
                .setMessage(mRationale)
                .setCancelable(false)
                .setPositiveButton(android.R.string.ok, null)
                .setOnDismissListener(new DialogInterface.OnDismissListener() {
                    @Override
                    public void onDismiss(DialogInterface dialog) {
                        componentRequestPermissions(permissions);
                    }
                })
                .show();
    }

    /**
     * 检查是否拥有权限
     *
     * @param context
     */
    public static boolean checkSelfPermissions(Context context, String... permissions) {
        boolean result = true;
        for (String permission : permissions) {
            int permissionCheck = ContextCompat.checkSelfPermission(context, permission);
            result &= permissionCheck == PackageManager.PERMISSION_GRANTED;
        }
        return result;
    }

    /**
     * 获取请求吗
     *
     * @return
     */
    public int getRequestCode() {
        return mRequestCode;
    }

    /**
     * 获取上下文对象
     *
     * @return
     */
    public Context getContext() {
        if (mContext == null) {
            if (mComponent == Component.ACTIVITY) {
                mContext = mActivity;
            } else if (mComponent == Component.FRAGMENT) {
                mContext = mFragment.getContext();
            }
        }
        return mContext;
    }

    public enum Component {
        ACTIVITY,
        FRAGMENT
    }


    private class PermissionsResultSourceImpl implements PermissionsResultSource {

        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            if (requestCode == getRequestCode()) {
                List<String> granted = new ArrayList<>();
                List<String> denied = new ArrayList<>();
                for (int i = 0; i < permissions.length; i++) {
                    if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                        granted.add(permissions[i]);
                    } else {
                        denied.add(permissions[i]);
                    }
                }
                mListener.onPermissionResult(mRequestCode, granted, denied);
            }
        }

        @Override
        public int getRequestCode() {
            return mRequestCode;
        }
    }

    /**
     * 权限请求者的构建器
     */
    public static class Builder {


        //告诉用户申请权限的理由
        private String mRequestRationale;
        //权限请求的处理结果监听
        private PermissionsListener mListener;
        //提供数据源
        private PermissionsSource mSource;
        //请求码
        private int mRequestCode = -1;
        private Activity mActivity;
        private Fragment mFragment;

        public Builder() {
        }


        /**
         * 当权限在首次申请被拒绝后，再次请求将会向用户说明申请权限的理由
         *
         * @param reqRationale 如果未配置胡或者设置空将不会有任何提示
         * @return Builder
         */
        public Builder reqRationale(String reqRationale) {
            this.mRequestRationale = reqRationale;
            return this;
        }


        /**
         * 当权限被拒绝或被同意时，将会通过该回调方法来通知调用者
         *
         * @param listener 权限结果监听器
         * @return Builder
         */
        public Builder listener(PermissionsListener listener) {
            this.mListener = listener;
            return this;
        }

        public <Source extends Activity & PermissionsSource> Builder source(Source activity) {
            this.mSource = activity;
            this.mActivity = activity;
            this.mFragment = null;
            return this;
        }

        public <Source extends Fragment & PermissionsSource> Builder source(Source fragment) {
            this.mSource = fragment;
            this.mActivity = null;
            this.mFragment = fragment;
            return this;
        }

        /**
         * 权限请求时需要一个请求码来区分各个请求
         *
         * @param code 请求码
         * @return Builder
         */
        public Builder requestCode(int code) {
            this.mRequestCode = code;
            return this;
        }


        /**
         * 确保能够构建对象
         */
        private void ensureRequest() {
            if (mRequestCode == -1) {
                throw new IllegalStateException("必须调用requestCode(int code)设置请求码");
            }
            if (mActivity == null && mFragment == null) {
                throw new IllegalStateException("source(Source source)设置提供响应值的源");
            }
        }

        /**
         * 构建对象
         *
         * @return
         */
        public PermissionsRequester build() {
            ensureRequest();
            Component component = mActivity == null ? Component.FRAGMENT : Component.ACTIVITY;
            return new PermissionsRequester(mRequestCode, mSource, mListener, mRequestRationale, component, mActivity, mFragment);
        }

    }
}
